#include "ASListItem.h"
#include "ASScrollText.h"

static as_ret as_ctrl_listitem_set_color(as_listitem* li_p, ASUINT* target_p, ASUINT color)
{
    if(!li_p || !target_p)
    {
        return AS_INVALID_PARAM;
    }

    *target_p = color;
    return AS_OK;
}

static as_ret as_ctrl_listitem_set_bg_color(as_control* ctrl_p, ASUINT color)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p)
    {
        return AS_INVALID_PARAM;
    }

    return as_ctrl_listitem_set_color(li_p, &li_p->bg_color, color);
}

static as_ret as_ctrl_listitem_set_bg_selected_color(as_control* ctrl_p, ASUINT color)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p)
    {
        return AS_INVALID_PARAM;
    }

    return as_ctrl_listitem_set_color(li_p, &li_p->bg_selected_color, color);
}

static as_ret as_ctrl_listitem_set_image(as_control* ctrl_p, as_image** target_p, ASWSTR path, as_image_src_type type)
{
    as_ret ret = AS_OK;
    as_listitem* li_p = (as_listitem*)ctrl_p;
    ASUINT param[3];

    if(!li_p || !path || as_wstrlen(path) <= 0 || !target_p)
    {
        ret = AS_INVALID_PARAM;
        return ret;
    }

    if(*target_p)
    {
        as_ctrl_destroy((as_control*)(*target_p));
    }

    param[0] = (ASUINT)type;
    param[1] = (ASUINT)path;
    param[2] = (ASUINT)FALSE;
    *target_p = (as_image*)as_ctrl_create(AS_CTRL_IMAGE, li_p->base.area, 3, (void**)param);

    if(*target_p == NULL)
    {
        ret = AS_INTERNAL_ERROR;
        return ret;
    }
    else
    {
        as_rect clip;
        memcpy(&clip, &(*target_p)->region, sizeof(as_rect));
        clip.w = AS_MIN((*target_p)->region.w, li_p->base.area.w);
        clip.h = AS_MIN((*target_p)->region.h, li_p->base.area.h);
        (*target_p)->set_region((as_control*)(*target_p), clip);
        (*target_p)->set_show_type((as_control*)(*target_p), AS_IMAGE_TILED);
        return AS_OK;
    }
}

static as_ret as_ctrl_listitem_set_bg_image(as_control* ctrl_p, ASWSTR path, as_image_src_type type)
{
    as_ret ret = AS_OK;
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p || !path || as_wstrlen(path) <= 0)
    {
        ret = AS_INVALID_PARAM;
        return ret;
    }

    return as_ctrl_listitem_set_image(ctrl_p, &li_p->bg_img, path, type);
}

static as_ret as_ctrl_listitem_set_bg_selected_image(as_control* ctrl_p, ASWSTR path, as_image_src_type type)
{
    as_ret ret = AS_OK;
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p || !path || as_wstrlen(path) <= 0)
    {
        ret = AS_INVALID_PARAM;
        return ret;
    }

    return as_ctrl_listitem_set_image(ctrl_p, &li_p->bg_selected_img, path, type);
}


static as_control* as_ctrl_listitem_get_ctrl_by_type(as_control* father_p, as_control_type type)
{
    as_control* ctrl_p = NULL;
    as_listitem* item_p = (as_listitem*)father_p;
    ASINT i;

    if(!item_p)
        return NULL;

    for(i = 0; i < item_p->cur_ctrl_counts; i++)
    {
        if(item_p->ctrls[i]->ctrl_type == type)
        {
            return item_p->ctrls[i];
        }
    }

    return ctrl_p;
}

static ASINT  as_ctrl_listitem_get_cur_ctrl_counts(as_control* father_p)
{
    as_listitem* li_p = (as_listitem*)father_p;

    if(!father_p)
        return 0;

    return li_p->cur_ctrl_counts;
}

static as_control* as_ctrl_listitem_add_ctrl(as_control* father_p, as_control_type type, as_rect area, ASINT extra_param_cnts, void** extra_param_p)
{
    as_listitem* li_p = (as_listitem*)father_p;
    as_control* ctrl_p = NULL;

    if(!father_p || !extra_param_p)
        return NULL;

    if(li_p->cur_ctrl_counts >= AS_LIST_ITEM_MAX_CONTROLS)
    {
        return NULL;
    }

    ctrl_p = as_ctrl_create(type, area, extra_param_cnts, extra_param_p);

    if(!ctrl_p)
        return NULL;

    li_p->ctrls[li_p->cur_ctrl_counts] = ctrl_p;
    li_p->cur_ctrl_counts++;
    return ctrl_p;
}

static as_ret as_ctrl_listitem_delete_ctrl(as_control* father_p, as_control* ctrl_p)
{
    as_listitem* li_p = (as_listitem*)father_p;
    ASINT i = 0, j;

    if(!li_p || !ctrl_p)
        return AS_INVALID_PARAM;

    for(i = 0; i < li_p->cur_ctrl_counts; i++)
    {
        if(li_p->ctrls[i] == ctrl_p)
        {
            break;
        }
    }

    if(i == li_p->cur_ctrl_counts)
    {
        return AS_INVALID_PARAM;
    }

    as_ctrl_destroy(li_p->ctrls[i]);
    li_p->ctrls[i] = NULL;

    for(j = i; j < li_p->cur_ctrl_counts - 1; j++)
    {
        li_p->ctrls[j] = li_p->ctrls[j + 1];
    }

    li_p->ctrls[li_p->cur_ctrl_counts - 1] = NULL;
    li_p->cur_ctrl_counts--;
    return AS_OK;
}

static as_ret as_ctrl_listitem_clear_ctrls(as_control* father_p)
{
    as_listitem* li_p = (as_listitem*)father_p;
    ASINT i = 0;

    if(!li_p)
        return AS_INVALID_PARAM;

    for(i = 0; i < ARRAY_SIZE(li_p->ctrls); i++)
    {
        if(li_p->ctrls[i])
        {
            as_ctrl_destroy(li_p->ctrls[i]);
            li_p->ctrls[i] = NULL;
        }
    }

    return AS_OK;
}

static void as_ctrl_listitem_move(as_control* father_p, ASINT x_off, ASINT y_off)
{
    as_listitem* li_p = (as_listitem*)father_p;
    ASINT i = 0;

    if(!li_p)
        return;

    li_p->base.area.x += (ASINT16)x_off;
    li_p->base.area.y += (ASINT16)y_off;

    if(li_p->bg_img)
        li_p->bg_img->base.move((as_control*)li_p->bg_img, x_off, y_off);

    if(li_p->bg_selected_img)
        li_p->bg_selected_img->base.move((as_control*)li_p->bg_selected_img, x_off, y_off);

    for(i = 0; i < li_p->cur_ctrl_counts; i++)
    {
        if(li_p->ctrls[i])
        {
            li_p->ctrls[i]->move(li_p->ctrls[i], x_off, y_off);
        }
    }
}

static as_ret as_ctrl_listitem_set_focus(as_control* father_p, ASINT if_focus)
{
    as_listitem* li_p = (as_listitem*)father_p;
    ASINT i;

    if(!li_p || if_focus == li_p->is_selected)
    {
        return AS_INVALID_PARAM;
    }

    if(!li_p->could_selected && if_focus)
        return AS_INVALID_PARAM;

    li_p->is_selected = if_focus;

    for(i = 0; i < li_p->cur_ctrl_counts; i++)
    {
        if(li_p->ctrls[i] && li_p->ctrls[i]->ctrl_type == AS_CTRL_SCROLLTEXT)
            ((as_scrolltext*)(li_p->ctrls[i]))->set_focus(li_p->ctrls[i], if_focus);
    }

    return AS_OK;
}

static ASINT as_ctrl_listitem_get_focus(as_control* father_p)
{
    as_listitem* li_p = (as_listitem*)father_p;

    if(!li_p)
    {
        return AS_INVALID_PARAM;
    }

    return li_p->is_selected;
}

static as_ret as_ctrl_listitem_set_prev_item(as_control* ctrl_p, as_listitem* prev_p)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!ctrl_p)
        return AS_INVALID_PARAM;

    li_p->prev_p = prev_p;
    return AS_OK;
}

static as_ret as_ctrl_listitem_set_next_item(as_control* ctrl_p, as_listitem* next_p)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!ctrl_p)
        return AS_INVALID_PARAM;

    li_p->next_p = next_p;
    return AS_OK;
}

static as_listitem* as_ctrl_listitem_get_prev_item(as_control* ctrl_p)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p)
        return NULL;

    return li_p->prev_p;
}

static as_listitem* as_ctrl_listitem_get_next_item(as_control* ctrl_p)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p)
        return NULL;

    return li_p->next_p;
}

static void as_ctrl_listitem_set_pen_down_cb(as_control* ctrl_p, as_listitem_cb cb)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p || !cb || li_p->pen_down_cb == cb)
        return;

    li_p->pen_down_cb = cb;
}

static void as_ctrl_listitem_set_pen_up_cb(as_control* ctrl_p, as_listitem_cb cb)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p || !cb || li_p->pen_up_cb == cb)
        return;

    li_p->pen_up_cb = cb;
}

static void as_ctrl_listitem_paint_bg(as_control* ctrl_p)
{
    as_rect* area_p;
    as_listitem* li_p = (as_listitem*)ctrl_p;
    ASUINT8* paint_buf;

    if(!li_p)
        return;

    area_p = &li_p->base.area;
    paint_buf = as_get_layer_buffer_by_hdlr(li_p->base.show_hdlr);

    if(li_p->is_selected == FALSE)
    {
        if(li_p->bg_img)
        {
            ((as_control*)li_p->bg_img)->paint_hdlr((as_control*)li_p->bg_img);
        }
        else
        {
            as_fill_rect(area_p, li_p->bg_color, li_p->bg_color);
        }
    }
    else
    {
        if(li_p->bg_selected_img)
        {
            ((as_control*)li_p->bg_selected_img)->paint_hdlr((as_control*)li_p->bg_selected_img);
        }
        else
        {
            as_fill_rect(area_p, li_p->bg_selected_color, li_p->bg_selected_color);
        }
    }
}

static void as_ctrl_listitem_paint(as_control* ctrl_p)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;
    ASINT i = 0, layer;

    if(!ctrl_p || ctrl_p->if_hidden)
        return;

    layer = ctrl_p->show_hdlr;

    if(layer < 0)
        return;

    if(as_set_layer_clip_ex(layer, &li_p->father_area) == AS_IGNORE)
        return;

    if(layer < 0 || as_set_layer_clip_ex(layer, &li_p->base.area) == AS_IGNORE)
        return;

    //first of all,draw bg
    li_p->paint_bg((as_control*)li_p);

    //than,draw each sub controls
    for(i = 0; i < li_p->cur_ctrl_counts; i++)
    {
        if(li_p->ctrls[i])
        {
            if(as_set_layer_clip_ex(layer, &li_p->father_area) == AS_IGNORE)
                continue;

            if(as_set_layer_clip_ex(layer, &li_p->base.area) == AS_IGNORE)
                continue;

            li_p->ctrls[i]->paint_hdlr(li_p->ctrls[i]);
            as_reset_clip();
        }
    }

    as_reset_layer_clip(layer);
}

static as_ret as_ctrl_listitem_pen_hdlr(as_control* ctrl_p, ASINT event, ASINT x, ASINT y)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;
    ASINT i;

    if(!li_p || ctrl_p->if_hidden)
        return AS_INVALID_PARAM;

    if(li_p->is_selected == TRUE && event == AS_EVT_TOUCH_DOWN && AS_POINT_IN_RECT(x, y, li_p->base.area))
    {
        for(i = li_p->cur_ctrl_counts - 1; i >= 0; i--)
        {
            if(AS_POINT_IN_RECT(x, y, li_p->ctrls[i]->area))
            {
                if(li_p->ctrls[i]->pen_hdlr)
                {
                    return li_p->ctrls[i]->pen_hdlr(li_p->ctrls[i], AS_EVT_TOUCH_DOWN, x, y);
                }
            }
        }

        if(li_p->pen_down_cb)
            li_p->pen_down_cb(li_p);

        //li_p->base.paint_hdlr(ctrl_p);
        //as_ctrl_flush();
        return AS_OK;
    }
    else if(li_p->is_selected == TRUE && event == AS_EVT_TOUCH_UP && AS_POINT_IN_RECT(x, y, li_p->base.area))
    {
        ASINT i;

        //li_p->is_selected = FALSE;
        //li_p->base.paint_hdlr(ctrl_p);
        //as_ctrl_flush();
        //callback
        for(i = li_p->cur_ctrl_counts - 1; i >= 0; i--)
        {
            if(AS_POINT_IN_RECT(x, y, li_p->ctrls[i]->area))
            {
                if(li_p->ctrls[i]->pen_hdlr)
                {
                    return li_p->ctrls[i]->pen_hdlr(li_p->ctrls[i], AS_EVT_TOUCH_UP, x, y);
                }
            }
        }

        if(li_p->pen_up_cb)
            li_p->pen_up_cb(li_p);

        return AS_OK;
    }
    else
    {
        return AS_IGNORE;
    }
}

static as_ret as_ctrl_listitem_key_hdlr(as_control* ctrl_p, ASINT event, ASINT keycode)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p || li_p->is_selected == FALSE || ctrl_p->if_hidden)
        return AS_INVALID_PARAM;

    if(keycode == AS_KEY_OK && event == AS_EVT_KEY_DOWN)
    {
        if(li_p->pen_down_cb)
        {
            li_p->pen_down_cb(li_p);
            return AS_OK;
        }
        else
            return AS_IGNORE;
    }
    else if(keycode == AS_KEY_OK && event == AS_EVT_KEY_UP)
    {
        if(li_p->pen_up_cb)
        {
            li_p->pen_up_cb(li_p);
            return AS_OK;
        }
        else
            return AS_IGNORE;
    }

    return AS_IGNORE;
}

static as_ret as_ctrl_listitem_save_father_area(as_control* ctrl_p, as_rect* area_p)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p || !area_p)
        return AS_INVALID_PARAM;

    memcpy(&li_p->father_area, area_p, sizeof(as_rect));
    return AS_OK;
}

static void as_ctrl_listitem_set_hidden(as_control* ctrl_p, ASINT if_hidden)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;
    ASINT i;

    if(!li_p)
        return;

    if(ctrl_p->if_hidden != if_hidden)
    {
        ctrl_p->if_hidden = if_hidden;

        for(i = 0; i < AS_LIST_ITEM_MAX_CONTROLS; i++)
        {
            if(li_p->ctrls[i])
            {
                li_p->ctrls[i]->set_hidden(li_p->ctrls[i], if_hidden);
            }
        }
    }
}

static as_ret as_ctrl_listitem_set_if_could_select(as_control* ctrl_p, ASINT if_could)
{
    as_listitem* li_p = (as_listitem*)ctrl_p;

    if(!li_p || li_p->could_selected == if_could)
        return AS_INVALID_PARAM;

    li_p->could_selected = if_could;
    return AS_OK;
}

as_listitem* as_ctrl_listitem_create(as_rect area, as_rect* father_area_p)
{
    as_listitem* li_p = NULL;
    li_p = as_calloc(sizeof(as_listitem));

    if(!li_p)
        return NULL;

    as_ctrl_init((as_control*)li_p, area);
    li_p->base.pen_hdlr = as_ctrl_listitem_pen_hdlr;
    li_p->base.key_hdlr = as_ctrl_listitem_key_hdlr;
    li_p->base.paint_hdlr = as_ctrl_listitem_paint;
    li_p->base.move = as_ctrl_listitem_move;
    li_p->base.ctrl_type = AS_CTRL_LISTITEM;
    li_p->base.set_hidden = as_ctrl_listitem_set_hidden;
    li_p->cur_ctrl_counts = 0;
    li_p->is_selected = FALSE;
    li_p->set_bg_color = as_ctrl_listitem_set_bg_color;
    li_p->set_bg_selected_color = as_ctrl_listitem_set_bg_selected_color;
    li_p->set_bg_image = as_ctrl_listitem_set_bg_image;
    li_p->set_bg_selected_image = as_ctrl_listitem_set_bg_selected_image;
    li_p->get_ctrl_by_type = as_ctrl_listitem_get_ctrl_by_type;
    li_p->add_ctrl = as_ctrl_listitem_add_ctrl;
    li_p->delete_ctrl = as_ctrl_listitem_delete_ctrl;
    li_p->clear_ctrls = as_ctrl_listitem_clear_ctrls;
    li_p->set_focus = as_ctrl_listitem_set_focus;
    li_p->get_focus = as_ctrl_listitem_get_focus;
    li_p->get_cur_ctrl_counts = as_ctrl_listitem_get_cur_ctrl_counts;
    li_p->set_prev_item = as_ctrl_listitem_set_prev_item;
    li_p->set_next_item = as_ctrl_listitem_set_next_item;
    li_p->get_prev_item = as_ctrl_listitem_get_prev_item;
    li_p->get_next_item = as_ctrl_listitem_get_next_item;
    li_p->save_father_area = as_ctrl_listitem_save_father_area;
    li_p->paint_bg = as_ctrl_listitem_paint_bg;
    li_p->save_father_area((as_control*)li_p, father_area_p);
    li_p->set_pen_down_cb = as_ctrl_listitem_set_pen_down_cb;
    li_p->set_pen_up_cb = as_ctrl_listitem_set_pen_up_cb;
    li_p->set_if_could_select = as_ctrl_listitem_set_if_could_select;
    li_p->could_selected = ASTRUE;
    return li_p;
}

as_ret as_ctrl_listitem_destroy(as_listitem* ctrl_listitem_p)
{
    if(!ctrl_listitem_p)
        return AS_INVALID_PARAM;

    if(ctrl_listitem_p->bg_selected_img)
    {
        as_ctrl_destroy((as_control*)ctrl_listitem_p->bg_selected_img);
        ctrl_listitem_p->bg_selected_img = NULL;
    }

    if(ctrl_listitem_p->bg_img)
    {
        as_ctrl_destroy((as_control*)ctrl_listitem_p->bg_img);
        ctrl_listitem_p->bg_img = NULL;
    }

    ctrl_listitem_p->clear_ctrls((as_control*)ctrl_listitem_p);
    as_free(ctrl_listitem_p);
    ctrl_listitem_p = NULL;
    return AS_OK;
}